package com.foreknow.spring;

import com.foreknow.bean.User;
import com.foreknow.service.UserService;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ClassPathXmlApplicationContext implements BeanFactory {
    private Map<String,Object> beans = new HashMap<>();
    public ClassPathXmlApplicationContext() throws JDOMException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //解析xml文件
        //1. 创建一个解析器
        SAXBuilder builder = new SAXBuilder();
        //2. 构造文档Document对象
        Document document = builder.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));
        //3. 获取到根节点
        Element root = document.getRootElement();
        //4. 获取到子节点
        List<Element> list = root.getChildren();
        //5. 遍历集合获取到每一个子节点
        for(int i = 0;i<list.size();i++){
            Element element = list.get(i);
            //获取id和class
            String id = element.getAttributeValue("id");
            String clazz = element.getAttributeValue("class");
            //需要将获取到的id和clazz保存到map集合中
            //需要通过反射将clazz转换为对象
            Object o = Class.forName(clazz).newInstance(); //当循环第二次获取到的对应UserServiceImpl对象
            beans.put(id,o);
            //获取子节点<property name="userDao" bean="u"></property>
            for (Element propertyElement:element.getChildren()) {
                String name = propertyElement.getAttributeValue("name"); //userDao
                String bean = propertyElement.getAttributeValue("bean"); //u
                //调用public void setUserDao(UserDao userDao)方法对接口进行初始化
                //通过Java中的反射来调用UserServiceImpl对象中的setUserDao(UserDao userDao)方法
                //从Map集合中根据u获取到value（UserDaoImpl对象）
                Object beanObject = beans.get(bean); //UserDaoImpl对象
                //拼接方法名
                String methodName = "set"+ name.substring(0,1).toUpperCase()+name.substring(1);
                //通过getInterfaces()可以获取到实现类所对应的接口
                Method method = o.getClass().getMethod(methodName,beanObject.getClass().getInterfaces()[0]);
                //调用方法
                // o表示要调用的set方法所属的对象(UserServiceImpl对象)
                // beanObject 实参(UserDaoImpl对象)
                method.invoke(o,beanObject);
            }
        }
    }
    @Override
    public Object getBean(String id) {
        return beans.get(id);
    }

    public static void main(String[] args) {
        try {

            BeanFactory beanFactory = new ClassPathXmlApplicationContext();
            UserService service = (UserService) beanFactory.getBean("userService");
            User user = service.getUserById(1);
            System.out.println(user.getUsername());

        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
